home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / lapb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  16.2 KB  |  692 lines

  1. /* Link Access Procedures Balanced (LAPB) - with changes for rational
  2.  * behavior over packet radio
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9. #include "ip.h"
  10. #include "netrom.h"
  11.  
  12. static void handleit __ARGS((struct ax25_cb *axp,char pid,struct mbuf *bp));
  13. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  14. static int ackours __ARGS((struct ax25_cb *axp,char n));
  15. static void clr_ex __ARGS((struct ax25_cb *axp));
  16. static void enq_resp __ARGS((struct ax25_cb *axp));
  17. static void inv_rex __ARGS((struct ax25_cb *axp));
  18.  
  19. #define    YES    1
  20. #define    NO    0
  21.  
  22. /* Process incoming frames */
  23. int
  24. lapb_input(axp,cmdrsp,bp)
  25. struct ax25_cb *axp;        /* Link control structure */
  26. int cmdrsp;            /* Command/response flag */
  27. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  28. {
  29.     char control;
  30.     char class;        /* General class (I/S/U) of frame */
  31.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  32.     char pf;        /* extracted poll/final bit */
  33.     char poll = 0;
  34.     char final = 0;
  35.     char nr;        /* ACK number of incoming frame */
  36.     char ns;        /* Seq number of incoming frame */
  37.     char tmp;
  38.  
  39.     if(bp == NULLBUF || axp == NULLAX25){
  40.         free_p(bp);
  41.         return -1;
  42.     }
  43.  
  44.     /* Extract the various parts of the control field for easy use */
  45.     control = pullchar(&bp);
  46.     type = ftype(control);
  47.     class = type & 0x3;
  48.     pf = control & PF;
  49.     /* Check for polls and finals */
  50.     if(pf){
  51.         switch(cmdrsp){
  52.         case LAPB_COMMAND:
  53.             poll = YES;
  54.             break;
  55.         case LAPB_RESPONSE:
  56.             final = YES;
  57.             break;
  58.         }
  59.     }
  60.     /* Extract sequence numbers, if present */
  61.     switch(class){
  62.     case I:
  63.     case I+2:
  64.         ns = (control >> 1) & MMASK;
  65.     case S:    /* Note fall-thru */
  66.         nr = (control >> 5) & MMASK;
  67.         break;
  68.     }
  69.     /* This section follows the SDL diagrams by K3NA fairly closely */
  70.     switch(axp->state){
  71.     case LAPB_DISCONNECTED:
  72.         switch(type){
  73.         case SABM:    /* Initialize or reset link */
  74.             sendctl(axp,LAPB_RESPONSE,UA|pf);    /* Always accept */
  75.             clr_ex(axp);
  76.             axp->unack = axp->vr = axp->vs = 0;
  77.             lapbstate(axp,LAPB_CONNECTED);/* Resets state counters */
  78.             axp->srt = Axirtt / MSPTICK;
  79.             axp->t1.start = 2*axp->srt;
  80.             start_timer(&axp->t3);
  81.             start_timer(&axp->t4);
  82.             break;
  83.         case DM:    /* Ignore to avoid infinite loops */
  84.             break;
  85.         default:    /* All others get DM */
  86.             if(poll)
  87.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  88.             break;
  89.         }
  90.         if(axp->state == LAPB_DISCONNECTED){    /* we can close connection */
  91.             stop_timer(&axp->t1);    /* waste all the timers */
  92.             stop_timer(&axp->t3);
  93.             stop_timer(&axp->t4);
  94.             free_q(&axp->txq);    /* lose transmit queue */
  95.             del_ax25(axp);        /* clean out the trash */
  96.         }
  97.         break;
  98.     case LAPB_SETUP:
  99.         switch(type){
  100.         case SABM:    /* Simultaneous open */
  101.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  102.             break;
  103.         case DISC:
  104.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  105.             break;
  106.         case UA:    /* Connection accepted */
  107.             /* Note: xmit queue not cleared */
  108.             stop_timer(&axp->t1);
  109.             start_timer(&axp->t3);
  110.             axp->unack = axp->vr = axp->vs = 0;
  111.             lapbstate(axp,LAPB_CONNECTED);
  112.             start_timer(&axp->t4);
  113.             break;            
  114.         case DM:    /* Connection refused */
  115.             free_q(&axp->txq);
  116.             stop_timer(&axp->t1);
  117.             axp->reason = LB_DM;
  118.             lapbstate(axp,LAPB_DISCONNECTED);
  119.             break;
  120.         default:    /* All other frames ignored */
  121.             break;
  122.         }
  123.         break;
  124.     case LAPB_DISCPENDING:
  125.         switch(type){
  126.         case SABM:
  127.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  128.             break;
  129.         case DISC:
  130.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  131.             break;
  132.         case UA:
  133.         case DM:
  134.             stop_timer(&axp->t1);
  135.             lapbstate(axp,LAPB_DISCONNECTED);
  136.             break;
  137.         default:    /* Respond with DM only to command polls */
  138.             if(poll)
  139.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  140.             break;
  141.         }
  142.         break;
  143.     case LAPB_CONNECTED:
  144.         switch(type){
  145.         case SABM:
  146.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  147.             clr_ex(axp);
  148.             free_q(&axp->txq);
  149.             stop_timer(&axp->t1);
  150.             start_timer(&axp->t3);
  151.             axp->unack = axp->vr = axp->vs = 0;
  152.             lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  153.             break;
  154.         case DISC:
  155.             free_q(&axp->txq);
  156.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  157.             stop_timer(&axp->t1);
  158.             stop_timer(&axp->t3);
  159.             axp->reason = LB_NORMAL;
  160.             lapbstate(axp,LAPB_DISCONNECTED);
  161.             break;
  162.         case DM:
  163.             axp->reason = LB_DM;
  164.             lapbstate(axp,LAPB_DISCONNECTED);
  165.             break;
  166.         case UA:
  167.             est_link(axp);
  168.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  169.             break;            
  170.         case FRMR:
  171.             est_link(axp);
  172.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  173.             break;
  174.         case RR:
  175.         case RNR:
  176.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  177.             if(poll)
  178.                 enq_resp(axp);
  179.             ackours(axp,nr);
  180.             break;
  181.         case REJ:
  182.             axp->flags.remotebusy = NO;
  183.             if(poll)
  184.                 enq_resp(axp);
  185.             ackours(axp,nr);
  186.             stop_timer(&axp->t1);
  187.             start_timer(&axp->t3);
  188.             /* This may or may not actually invoke transmission,
  189.              * depending on whether this REJ was caused by
  190.              * our losing his prior ACK.
  191.              */
  192.             inv_rex(axp);
  193.             break;    
  194.         case I:
  195.             ackours(axp,nr); /** == -1) */
  196.             start_timer(&axp->t4);
  197.             if(len_p(axp->rxq) >= axp->window){
  198.                 /* Too bad he didn't listen to us; he'll
  199.                  * have to resend the frame later. This
  200.                  * drastic action is necessary to avoid
  201.                  * deadlock.
  202.                  */
  203.                 if(poll)
  204.                     sendctl(axp,LAPB_RESPONSE,RNR|pf);
  205.                 free_p(bp);
  206.                 bp = NULLBUF;
  207.                 break;
  208.             }
  209.             /* Reject or ignore I-frames with receive sequence number errors */
  210.             if(ns != axp->vr){
  211.                 if(axp->proto == V1 || !axp->flags.rejsent){
  212.                     axp->flags.rejsent = YES;
  213.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  214.                 } else if(poll)
  215.                     enq_resp(axp);
  216.                 axp->response = 0;
  217.                 break;
  218.             }
  219.             axp->flags.rejsent = NO;
  220.             axp->vr = (axp->vr+1) & MMASK;
  221.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  222.             if(poll){
  223.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  224.             } else {
  225.                 axp->response = tmp;
  226.             }
  227.             procdata(axp,bp);
  228.             bp = NULLBUF;
  229.             break;
  230.         default:    /* All others ignored */
  231.             break;
  232.         }
  233.         break;
  234.     case LAPB_RECOVERY:
  235.         switch(type){
  236.         case SABM:
  237.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  238.             clr_ex(axp);
  239.             stop_timer(&axp->t1);
  240.             start_timer(&axp->t3);
  241.             axp->unack = axp->vr = axp->vs = 0;
  242.             lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  243.             if(!run_timer(&axp->t4))
  244.                 start_timer(&axp->t4);
  245.             break;
  246.         case DISC:
  247.             free_q(&axp->txq);
  248.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  249.             stop_timer(&axp->t1);
  250.             stop_timer(&axp->t3);
  251.             axp->response = UA;
  252.             axp->reason = LB_NORMAL;
  253.             lapbstate(axp,LAPB_DISCONNECTED);
  254.             break;
  255.         case DM:
  256.             axp->reason = LB_DM;
  257.             lapbstate(axp,LAPB_DISCONNECTED);
  258.             break;
  259.         case UA:
  260.             est_link(axp);
  261.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  262.             break;
  263.         case FRMR:
  264.             est_link(axp);
  265.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  266.             break;
  267.         case RR:
  268.         case RNR:
  269.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  270.             if(axp->proto == V1 || final){
  271.                 stop_timer(&axp->t1);
  272.                 ackours(axp,nr);
  273.                 if(axp->unack != 0){
  274.                     inv_rex(axp);
  275.                 } else {
  276.                     start_timer(&axp->t3);
  277.                     lapbstate(axp,LAPB_CONNECTED);
  278.                     if(!run_timer(&axp->t4))
  279.                         start_timer(&axp->t4);
  280.                 }
  281.             } else {
  282.                 if(poll)
  283.                     enq_resp(axp);
  284.                 ackours(axp,nr);
  285.                 /* Keep timer running even if all frames
  286.                  * were acked, since we must see a Final
  287.                  */
  288.                 if(!run_timer(&axp->t1))
  289.                     start_timer(&axp->t1);
  290.             }
  291.             break;
  292.         case REJ:
  293.             axp->flags.remotebusy = NO;
  294.             /* Don't insist on a Final response from the old proto */
  295.             if(axp->proto == V1 || final){
  296.                 stop_timer(&axp->t1);
  297.                 ackours(axp,nr);
  298.                 if(axp->unack != 0){
  299.                     inv_rex(axp);
  300.                 } else {
  301.                     start_timer(&axp->t3);
  302.                     lapbstate(axp,LAPB_CONNECTED);
  303.                     if(!run_timer(&axp->t4))
  304.                         start_timer(&axp->t4);
  305.                 }
  306.             } else {
  307.                 if(poll)
  308.                     enq_resp(axp);
  309.                 ackours(axp,nr);
  310.                 if(axp->unack != 0){
  311.                     /* This is certain to trigger output */
  312.                     inv_rex(axp);
  313.                 }
  314.                 /* A REJ that acks everything but doesn't
  315.                  * have the F bit set can cause a deadlock.
  316.                  * So make sure the timer is running.
  317.                  */
  318.                 if(!run_timer(&axp->t1))
  319.                     start_timer(&axp->t1);
  320.             }
  321.             break;
  322.         case I:
  323.             ackours(axp,nr); /** == -1) */
  324.             /* Make sure timer is running, since an I frame
  325.              * cannot satisfy a poll
  326.              */
  327.             if(!run_timer(&axp->t1))
  328.                 start_timer(&axp->t1);
  329.             if(len_p(axp->rxq) >= axp->window){
  330.                 /* Too bad he didn't listen to us; he'll
  331.                  * have to resend the frame later. This
  332.                  * drastic action is necessary to avoid
  333.                  * memory deadlock.
  334.                  */
  335.                 sendctl(axp,LAPB_RESPONSE,RNR | pf);
  336.                 free_p(bp);
  337.                 bp = NULLBUF;
  338.                 break;
  339.             }
  340.             /* Reject or ignore I-frames with receive sequence number errors */
  341.             if(ns != axp->vr){
  342.                 if(axp->proto == V1 || !axp->flags.rejsent){
  343.                     axp->flags.rejsent = YES;
  344.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  345.                 } else if(poll)
  346.                     enq_resp(axp);
  347.  
  348.                 axp->response = 0;
  349.                 break;
  350.             }
  351.             axp->flags.rejsent = NO;
  352.             axp->vr = (axp->vr+1) & MMASK;
  353.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  354.             if(poll){
  355.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  356.             } else {
  357.                 axp->response = tmp;
  358.             }
  359.             procdata(axp,bp);
  360.             bp = NULLBUF;
  361.             break;
  362.         default:
  363.             break;        /* Ignored */
  364.         }
  365.         break;
  366.     }
  367.     free_p(bp);    /* In case anything's left */
  368.  
  369.     /* See if we can send some data, perhaps piggybacking an ack.
  370.      * If successful, lapb_output will clear axp->response.
  371.      */
  372.     lapb_output(axp);
  373.     if(axp->response != 0){
  374.         sendctl(axp,LAPB_RESPONSE,axp->response);
  375.         axp->response = 0;
  376.     }
  377.     return 0;
  378. }
  379. /* Handle incoming acknowledgements for frames we've sent.
  380.  * Free frames being acknowledged.
  381.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  382.  */
  383. static int
  384. ackours(axp,n)
  385. struct ax25_cb *axp;
  386. char n;
  387. {    
  388.     struct mbuf *bp;
  389.     int acked = 0;    /* Count of frames acked by this ACK */
  390.     int16 oldest;    /* Seq number of oldest unacked I-frame */
  391.  
  392.     /* Free up acknowledged frames by purging frames from the I-frame
  393.      * transmit queue. Start at the remote end's last reported V(r)
  394.      * and keep going until we reach the new sequence number.
  395.      * If we try to free a null pointer,
  396.      * then we have a frame reject condition.
  397.      */
  398.     oldest = (axp->vs - axp->unack) & MMASK;
  399.     while(axp->unack != 0 && oldest != n){
  400.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  401.             /* Acking unsent frame */
  402.             return -1;
  403.         }
  404.         free_p(bp);
  405.         axp->unack--;
  406.         acked++;
  407.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  408.             /* A frame being timed has been acked */
  409.             axp->flags.rtt_run = 0;
  410.             /* Update only if frame wasn't retransmitted */
  411.             if(!axp->flags.retrans)
  412.                 axp->srt = ((axp->srt * 7) +
  413.                  (Clock - axp->rtt_time)) >> 3;
  414.         }
  415.         axp->flags.retrans = 0;
  416.         axp->retries = 0;
  417.         oldest = (oldest + 1) & MMASK;
  418.     }
  419.     if(axp->unack == 0){
  420.         /* All frames acked, stop timeout */
  421.         stop_timer(&axp->t1);
  422.         start_timer(&axp->t3);
  423.     } else if(acked != 0) { 
  424.         /* Partial ACK; restart timer */
  425.         start_timer(&axp->t1);
  426.     }
  427.     if(acked != 0){
  428.         /* If user has set a transmit upcall, indicate how many frames
  429.          * may be queued
  430.          */
  431.         if(axp->t_upcall != NULLVFP)
  432.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  433.     }
  434.     return 0;
  435. }
  436.  
  437. /* Establish data link */
  438. void
  439. est_link(axp)
  440. struct ax25_cb *axp;
  441. {
  442.     clr_ex(axp);
  443.     axp->retries = 0;
  444.     sendctl(axp,LAPB_COMMAND,SABM|PF);
  445.     stop_timer(&axp->t3);
  446.     start_timer(&axp->t1);
  447. }
  448. /* Clear exception conditions */
  449. static void
  450. clr_ex(axp)
  451. struct ax25_cb *axp;
  452. {
  453.     axp->flags.remotebusy = NO;
  454.     axp->flags.rejsent = NO;
  455.     axp->response = 0;
  456.     stop_timer(&axp->t3);
  457. }
  458. /* Enquiry response */
  459. static void
  460. enq_resp(axp)
  461. struct ax25_cb *axp;
  462. {
  463.     char ctl;
  464.  
  465.     ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  466.     sendctl(axp,LAPB_RESPONSE,ctl);
  467.     axp->response = 0;
  468.     stop_timer(&axp->t3);
  469. }
  470. /* Invoke retransmission */
  471. static void
  472. inv_rex(axp)
  473. struct ax25_cb *axp;
  474. {
  475.     axp->vs -= axp->unack;
  476.     axp->vs &= MMASK;
  477.     axp->unack = 0;
  478. }
  479. /* Send S or U frame to currently connected station */
  480. int
  481. sendctl(axp,cmdrsp,cmd)
  482. struct ax25_cb *axp;
  483. int cmdrsp;
  484. int cmd;
  485. {
  486.     if((ftype((char)cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  487.         cmd |= (axp->vr << 5);
  488.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  489. }
  490. /* Start data transmission on link, if possible
  491.  * Return number of frames sent
  492.  */
  493. int
  494. lapb_output(axp)
  495. register struct ax25_cb *axp;
  496. {
  497.     register struct mbuf *bp;
  498.     struct mbuf *tbp;
  499.     char control;
  500.     int sent = 0;
  501.     int i;
  502.  
  503.     if(axp == NULLAX25
  504.      || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  505.      || axp->flags.remotebusy)
  506.         return 0;
  507.  
  508.     /* Dig into the send queue for the first unsent frame */
  509.     bp = axp->txq;
  510.     for(i = 0; i < axp->unack; i++){
  511.         if(bp == NULLBUF)
  512.             break;    /* Nothing to do */
  513.         bp = bp->anext;
  514.     }
  515.     /* Start at first unsent I-frame, stop when either the
  516.      * number of unacknowledged frames reaches the maxframe limit,
  517.      * or when there are no more frames to send
  518.      */
  519.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  520.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  521.         axp->vs &= MMASK;
  522.         dup_p(&tbp,bp,0,len_p(bp));
  523.         if(tbp == NULLBUF)
  524.             return sent;    /* Probably out of memory */
  525.         sendframe(axp,LAPB_COMMAND,control,tbp);
  526.         start_timer(&axp->t4);
  527.         axp->unack++;
  528.         /* We're implicitly acking any data he's sent, so stop any
  529.          * delayed ack
  530.          */
  531.         axp->response = 0;
  532.         /* Use clamped backoff algorithm */
  533.         if(!axp->flags.retrans)
  534.             axp->t1.start = 2 * (axp->srt << axp->retries);
  535.         if(!run_timer(&axp->t1)){
  536.             stop_timer(&axp->t3);
  537.             start_timer(&axp->t1);
  538.         }
  539.         sent++;
  540.         bp = bp->anext;
  541.         if(!axp->flags.rtt_run){
  542.             /* Start round trip timer */
  543.             axp->rtt_seq = (control >> 1) & MMASK;
  544.             axp->rtt_time = Clock;
  545.             axp->flags.rtt_run = 1;
  546.         }
  547.     }
  548.     return sent;
  549. }
  550. /* Set new link state */
  551. void
  552. lapbstate(axp,s)
  553. struct ax25_cb *axp;
  554. int s;
  555. {
  556.     int oldstate;
  557.  
  558.     oldstate = axp->state;
  559.     axp->state = s;
  560.     if(s == LAPB_DISCONNECTED){
  561.         stop_timer(&axp->t1);
  562.         stop_timer(&axp->t3);
  563.         stop_timer(&axp->t4);
  564.         free_q(&axp->txq);
  565.     }
  566.     /* Don't bother the client unless the state is really changing */
  567.     if(oldstate != s && axp->s_upcall != NULLVFP)
  568.         (*axp->s_upcall)(axp,oldstate,s);
  569. }
  570. /* Process a valid incoming I frame */
  571. static void
  572. procdata(axp,bp)
  573. struct ax25_cb *axp;
  574. struct mbuf *bp;
  575. {
  576.     char pid;
  577.     char seq;
  578.  
  579.     /* Extract level 3 PID */
  580.     if(pullup(&bp,&pid,1) != 1)
  581.         return;    /* No PID */
  582.  
  583.     if(axp->segremain != 0){
  584.         /* Reassembly in progress; continue */
  585.         pullup(&bp,&seq,1);
  586.         if(uchar(pid) == PID_SEGMENT
  587.          && (seq & SEG_REM) == axp->segremain - 1){
  588.             /* Correct, in-order segment */
  589.             append(&axp->rxasm,bp);
  590.             if((axp->segremain = (seq & SEG_REM)) == 0){
  591.                 /* Done; kick it upstairs */
  592.                 bp = axp->rxasm;
  593.                 axp->rxasm = NULLBUF;
  594.                 pullup(&bp,&pid,1);
  595.                 handleit(axp,pid,bp);
  596.             }
  597.         } else {
  598.             /* Error! */
  599.             free_p(axp->rxasm);
  600.             axp->rxasm = NULLBUF;
  601.             axp->segremain = 0;
  602.             free_p(bp);
  603.         }
  604.     } else {
  605.         /* No reassembly in progress */
  606.         if(uchar(pid) == PID_SEGMENT){
  607.             /* Start reassembly */
  608.             pullup(&bp,&seq,1);
  609.             if(!(seq & SEG_FIRST)){
  610.                 free_p(bp);    /* not first seg - error! */
  611.             } else {
  612.                 /* Put first segment on list */
  613.                 axp->segremain = seq & SEG_REM;
  614.                 axp->rxasm = bp;
  615.             }
  616.         } else {
  617.             /* Normal frame; send upstairs */
  618.             handleit(axp,pid,bp);
  619.         }
  620.     }
  621. }
  622. /* New-style frame segmenter. Returns queue of segmented fragments, or
  623.  * original packet if small enough
  624.  */
  625. struct mbuf *
  626. segmenter(bp,ssize)
  627. struct mbuf *bp;    /* Complete packet */
  628. int16 ssize;        /* Max size of frame segments */
  629. {
  630.     struct mbuf *result = NULLBUF;
  631.     struct mbuf *bptmp,*bp1;
  632.     int16 len,offset;
  633.     int segments;
  634.  
  635.     /* See if packet is too small to segment. Note 1-byte grace factor
  636.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  637.      */
  638.     len = len_p(bp);
  639.     if(len <= ssize+1)
  640.         return bp;    /* Too small to segment */
  641.  
  642.     ssize -= 2;        /* ssize now equal to data portion size */
  643.     segments = 1 + (len - 1) / ssize;    /* # segments  */
  644.     offset = 0;
  645.  
  646.     while(segments != 0){
  647.         offset += dup_p(&bptmp,bp,offset,ssize);
  648.         if(bptmp == NULLBUF){
  649.             free_q(&result);
  650.             break;
  651.         }
  652.         /* Make room for segmentation header */
  653.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  654.             free_p(bptmp);
  655.             free_q(&result);
  656.             break;
  657.         }
  658.         bp1->data[0] = PID_SEGMENT;
  659.         bp1->data[1] = --segments;
  660.         if(offset == ssize)
  661.             bp1->data[1] |= SEG_FIRST;
  662.         enqueue(&result,bp1);
  663.     }
  664.     free_p(bp);
  665.     return result;
  666. }
  667.  
  668. static void
  669. handleit(axp,pid,bp)
  670. struct ax25_cb *axp;
  671. char pid;
  672. struct mbuf *bp;
  673. {
  674.     switch(uchar(pid)){
  675.     case PID_IP:        /* DoD Internet Protocol */
  676.         ip_route(axp->iface,bp,0);
  677.         break;
  678.     case PID_NO_L3:        /* Enqueue for application */
  679.         append(&axp->rxq,bp);
  680.         if(axp->r_upcall != NULLVFP)
  681.             (*axp->r_upcall)(axp,len_p(axp->rxq));
  682.         break;    
  683.     case PID_NETROM:
  684.         nr_route(bp,axp);
  685.         break;
  686.     default:        /* Note: ARP is invalid here */    
  687.         free_p(bp);
  688.         break;            
  689.     }
  690. }
  691.  
  692.